package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/protos/peer"
	"strconv"
	"time"
)

const (
	TransactionKeyPrefix  = "transaction"
	TxStatusNew           = "新建（待确认）"
	TxStatusConfirm       = "新建（已确认）"
	TxStatusPayForAnother = "申请代付"
	TxStatusPay           = "已付款（未核实）"
	TxStatusPayed         = "已付款（已核实）"
	TxStatusRefusePay     = "代付被拒"
	TxStatusShip          = "已发货（未核实）"
	TxstatusShiped        = "已发货（已核实）"
	TxStatusRepay         = "已还款（未核实）"
	TxStatusRepayed       = "已还款（已核实）"
)

type SupplyChainFinance struct {
}

// 	新建 -> 已确认 -> 申请代付 -> 已付款 ->确认付款-> 已发货 -> 确认发货 -> 已还款 -> 确认已还款
//                       |
//                    拒绝付款 ->回到上一步
type Transaction struct {
	Id                string    `json:"id"`                  // 单号
	Description       string    `json:"description"`         // 备注
	Value             uint64    `json:"value"`               // 金额(单位为一分钱)
	ShipmentNumber    string    `json:"shipment_number"`     // 物流号
	PaymentTxNumber   string    `json:"payment_tx_number"`   // 付款转账号
	RepaymentTxNumber string    `json:"repayment_tx_number"` // 还款转账号
	Status            string    `json:"status"`              // 订单状态      ----请使用上面const中的常量来标记订单状态
	CreateDate        time.Time `json:"create_date"`         // 创建时间
	PaymentDate       time.Time `json:"payment_date"`        // 付款时间
	RepaymentDate     time.Time `json:"repayment_date"`      // 应还款时间
	RepayDate         time.Time `json:"repay_date"`          // 实际还款时间
	Supplier          string    `json:"supplier"`            // 供应商
	Company           string    `json:"company"`             // 采购商
	FinancialOrg      string    `json:"financial_org"`       // 金融机构
}

type Company struct {
	Name           string    `json:"name"`            //企业名
	Phone          string    `json:"phone"`           //联系电话
	Account        string    `json:"account"`         //登录账号
	Password       string    `json:"password"`        //登录密码
	Address        string    `json:"address"`         //地址
	CompanyType    string    `json:"company_type"`    //企业类型，供应商，采购商，金融机构
	EnterpriseCode string    `json:"enterprise_code"` //企业统一社会信用代码
	BankCard       string    `json:"bank_card"`       //银行卡号码
	Balance        uint64    `json:"balance"`         //余额
	CreateDate     time.Time `json:"create_date"`     //创建时间
}

// 企业的3种类型
var companyArg = map[string]string{"financial_org": "financial_org", "supplier": "supplier", "buyer": "buyer"}

/**
  @Author: dd
  @Date:   2020/5/13 16:22
  @Desc:   智能合约初始化，要求必须创建3个企业，分别为供应商、采购商、金融企业 ,Company.Name="datainsights" （必需） *
  @Param:
  @Return:
**/
func (s *SupplyChainFinance) Init(stub shim.ChaincodeStubInterface) peer.Response {
	//实例化三个企业
	comp1:=Company{
		Name:           "金融机构",
		Phone:          "21131",
		Account:        "1001",
		Password:       "123456",
		Address:        "test",
		CompanyType:    companyArg["financial_org"],
		EnterpriseCode: "test",
		BankCard:       "20000122123",
		Balance:        20000,
		CreateDate:     time.Now(),
	}
	comp2:=Company{
		Name:           "供应商",
		Phone:          "21135311",
		Account:        "1002",
		Password:       "123456",
		Address:        "test",
		CompanyType:    companyArg["supplier"],
		EnterpriseCode: "test",
		BankCard:       "5344123",
		Balance:        20000,
		CreateDate:     time.Now(),
	}
	comp3:=Company{
		Name:           "采购商",
		Phone:          "12312313",
		Account:        "1003",
		Password:       "123456",
		Address:        "test",
		CompanyType:    companyArg["buyer"],
		EnterpriseCode: "test",
		BankCard:       "21223123",
		Balance:        20000,
		CreateDate:     time.Now(),
	}
	//存入数组
	comps:=[]Company{comp1,comp2,comp3}
	//遍历数组
	for i:=0;i<len(comps);i++{
		//序列化
		compByte,err:=json.Marshal(comps[i])
		if err != nil {
			return shim.Error("marshal error ")
		}
		res:=createCompany(stub,[]string{string(compByte)})
		if res.Status!=shim.OK{
			return peer.Response{
				Status:               res.Status,
				Message:              res.Message,
				Payload:              nil,
				XXX_NoUnkeyedLiteral: struct{}{},
				XXX_unrecognized:     nil,
				XXX_sizecache:        0,
			}
		}
	}
	return shim.Success(nil)
}

func (s *SupplyChainFinance) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	funcName, args := stub.GetFunctionAndParameters()

	switch funcName {
	case "newTransaction":
		return newTransaction(stub, args)
	case "createCompany":
		return createCompany(stub, args)
	case "confirmTransaction":
		return confirmTransaction(stub, args)
	case "applyPayForAnother":
		return applyPayForAnother(stub, args)
	case "payTransaction":
		return payTransaction(stub, args)
	case "affirmPay":
		return affirmPay(stub, args)
	case "refusePayTransaction":
		return refusePayTransaction(stub, args)
	case "updateShipmentInfo":
		return updateShipmentInfo(stub, args)
	case "verifyShipmentInfo":
		return verifyShipmentInfo(stub, args)
	case "repayTransaction":
		return repayTransaction(stub, args)
	case "verifyRepay":
		return verifyRepay(stub, args)
	case "autoRepay":
		return autoRepay(stub, args)
	case "getTransactions":
		return getTransactions(stub, args)
	case "getTrByBuyer":
		return getTrByBuyer(stub, args)
	case "getTransactionHistory":
		return getTransactionHistory(stub, args)
	case "getCompany":
		return getCompany(stub, args)
	default:
		return shim.Error(fmt.Sprintf("unsupported function: %s", funcName))
	}
}

/**
  @Author: dd
  @Date:   2020/5/13 16:48
  @Desc:   根据company.CompanyType来创建3种不同的企业*
  @Param:  Company
  @Return: res = peer.Response,       要求返回结果时能够返回正确相应的响应码：shim.ERROR,shim.ERRORTHRESHOLD,shim.OK
**/
func createCompany(stub shim.ChaincodeStubInterface, args []string) peer.Response {
//	验证参数
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
			XXX_NoUnkeyedLiteral: struct{}{},
			XXX_unrecognized:     nil,
			XXX_sizecache:        0,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
// 反序列化
	var comp Company
	if err:=json.Unmarshal([]byte(args[0]),&comp);err!=nil{
		return shim.Error("unmarshal error ")
	}
//	验证参数
	if comp.Account==""||comp.Address==""||comp.Balance<0||comp.BankCard==""||comp.EnterpriseCode==""||comp.Name==""||comp.Password==""||comp.Phone==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "必要参数为空",
			Payload:              nil,
		}
	}
	if comp.CompanyType!=companyArg["financial_org"]||comp.CompanyType!=companyArg["supplier"]||comp.CompanyType!=companyArg["buyer"]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "没有此企业类型",
			Payload:              nil,
		}
	}
//	创建组合键
	compKey,err:=stub.CreateCompositeKey(comp.CompanyType,[]string{comp.Name})
	if err != nil {
		return shim.Error("create key error ")
	}
//	序列化存入账本
	compByte,err:=json.Marshal(comp)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(compKey,compByte);err!=nil{
		return shim.Error("put state error ")
	}
	return shim.Success(compByte)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:01
  @Desc:   创建新的交易 *
  @Param:  {id:string, Value:int, supplier:string, create_date:time.Time, company:string}
  @Return:
**/
func newTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
//	反序列化
	var tran Transaction
	if err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
//	验证必要参数
	if tran.Id==""||tran.Value<0||tran.Supplier==""||tran.Company==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空或者订单金额小于0",
			Payload:              nil,
		}
	}
	//if !valideCompany(stub,companyArg["supplier"],tran.Supplier){
	//	return peer.Response{
	//		Status:               shim.ERRORTHRESHOLD,
	//		Message:              "未找到此企业",
	//		Payload:              nil,
	//	}
	//}
	//if !valideCompany(stub,companyArg["buyer"],tran.Company){
	//	return peer.Response{
	//		Status:               shim.ERRORTHRESHOLD,
	//		Message:              "未找到此企业",
	//		Payload:              nil,
	//	}
	//}
//	修改订单状态
	 tran.Status=TxStatusNew
//	 创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})
	if err != nil {
		return shim.Error("create key error ")
	}
//	序列化存入账本
	tranByte,err:=json.Marshal(tran)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByte);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByte)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:00
  @Desc:   供应商确认交易 *
  @Param:  {id:string, supplier:string}
  @Return:
**/
func confirmTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=2{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""||args[1]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal(tranByte,&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran.Supplier!=args[1]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran.Status!=TxStatusNew{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran.Status=TxStatusConfirm
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:57
  @Desc:   向金融机构申请代付 *
  @Param:  {id:string, company:string, financial_org:string, repayment_date:time.Time}
  @Return:
**/
func applyPayForAnother(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证必要参数
	if tran.Id==""||tran.Company==""||tran.FinancialOrg==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	// 判断是否存在此企业
	if !valideCompany(stub,companyArg["financial_org"],tran.FinancialOrg){
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "未找到此企业",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran1 Transaction
	if err:=json.Unmarshal(tranByte,&tran1);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran1.Company!=tran.Company{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran1.Status!=TxStatusRefusePay||tran1.Status!=TxStatusConfirm{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//	修改订单状信息
	tran1.Status=TxStatusPayForAnother
	tran1.RepaymentDate=tran.RepaymentDate
	tran1.FinancialOrg=tran.FinancialOrg
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran1)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:57
  @Desc:   付款  *
  @Param:  {id:string,PaymentTxNumber:string,financial_org:string,payment_date:time.Time}
  @Return:
**/
func payTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证必要参数
	if tran.Id==""||tran.PaymentTxNumber==""||tran.FinancialOrg==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran1 Transaction
	if err:=json.Unmarshal(tranByte,&tran1);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran1.FinancialOrg!=tran.FinancialOrg{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran1.Status!=TxStatusPayForAnother{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//执行转账
	res:=transferAccounts(stub,tran1.FinancialOrg,companyArg["financial_org"],tran1.Supplier,companyArg["supplier"],tran1.Value)
	if res.Status!=shim.OK{
		return peer.Response{
			Status:               res.Status,
			Message:              res.Message,
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran1.Status=TxStatusPay
	tran1.PaymentTxNumber=tran.PaymentTxNumber
	tran1.PaymentDate=tran.PaymentDate
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran1)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:00
  @Desc:   供应商核实付款 *
  @Param:  {id:string, supplier:string}
  @Return:
**/
func affirmPay(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=2{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""||args[1]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal(tranByte,&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran.Supplier!=args[1]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran.Status!=TxStatusPay{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran.Status=TxStatusPayed
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByte)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:55
  @Desc:   拒绝付款要求  *
  @Param:  {id:string,description:string,financial_org:string}
  @Return:
**/
func refusePayTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=3{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""||args[1]==""||args[2]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal(tranByte,&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran.FinancialOrg!=args[2]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran.Status!=TxStatusPayForAnother||tran.Status!=TxStatusRefusePay{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran.Status=TxStatusRefusePay
	tran.Description=args[1]
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:54
  @Desc:   供应商发货  *
  @Param:  {id:string,shipment_number:string,supplier:string}
  @Return:
**/
func updateShipmentInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=3{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""||args[1]==""||args[2]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal(tranByte,&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran.Supplier!=args[2]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran.Status!=TxStatusPayed{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran.Status=TxStatusShip
	tran.ShipmentNumber=args[1]
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:53
  @Desc:   买方收货  *
  @Param:  {id:string,company:string}
  @Return:
**/
func verifyShipmentInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=2{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""||args[1]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal(tranByte,&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran.Company!=args[1]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran.Status!=TxStatusShip{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran.Status=TxstatusShiped
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:50
  @Desc:   买方还款  *
  @Param:  {id:string,repayment_tx_number:string,tx_to_update:time.Time,company:string}
  @Return:
**/
func repayTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证必要参数
	if tran.Id==""||tran.RepaymentTxNumber==""||tran.Company==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran1 Transaction
	if err:=json.Unmarshal(tranByte,&tran1);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran1.Company!=tran.Company{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran1.Status!=TxstatusShiped{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//执行转账
	res:=transferAccounts(stub,tran1.Company,companyArg["buyer"],tran1.FinancialOrg,companyArg["financial_org"],tran1.Value)
	if res.Status!=shim.OK{
		return peer.Response{
			Status:               res.Status,
			Message:              res.Message,
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran1.Status=TxStatusRepay
	tran1.RepaymentTxNumber=tran.RepaymentTxNumber
	tran1.RepayDate=tran.RepayDate
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran1)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:48
  @Desc:   金融机构确认还款  *
  @Param:  {id:string,financial_org:string}
  @Return:
**/
func verifyRepay(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args)!=2{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""||args[1]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	//创建组合键
	tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})
	if err != nil {
		return shim.Error("create error ")
	}
	// 从账本中获取数据
	tranByte,err:=stub.GetState(tranKey)
	if err != nil {
		return shim.Error("get state error ")
	}
	//	反序列化
	var tran Transaction
	if err:=json.Unmarshal(tranByte,&tran);err!=nil{
		return shim.Error("unmarshal error")
	}
	//	验证是否拥有权限
	if tran.FinancialOrg!=args[1]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "无权限修改此订单",
			Payload:              nil,
		}
	}
	// 判断订单状态
	if tran.Status!=TxStatusRepay{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "订单状态出错",
			Payload:              nil,
		}
	}
	//	修改订单信息
	tran.Status=TxStatusRepayed
	//	序列化存入账本
	tranByteNew,err:=json.Marshal(tran)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(tranKey,tranByteNew);err!=nil{
		return shim.Error("put state error  ")
	}
	return shim.Success(tranByteNew)
}
/**
  @Author: dd
  @Date:   2020/5/15 17:48
  @Desc:   自动还款 *
  @Param:  { time:string }
  @Return:
**/
func autoRepay(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	//验证参数
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	nowTime,err:=time.Parse("2006-01-02 13:04:05",args[0])
	if err != nil {
		return shim.Error("time parse error")
	}
//	获取所有订单
	//	查询所有订单
	res:=getTransactions(stub,[]string{})
	if res.Status!=shim.OK{
		return peer.Response{
			Status:               res.Status,
			Message:              res.Message,
			Payload:              nil,
		}
	}
	// 反序列化
	var trans []Transaction
	if err:=json.Unmarshal(res.Payload,&trans);err!=nil{
		return shim.Error("unmarshal error ")
	}
//	遍历数组
	for i:=0;i<len(trans);i++{
		//判断是否超时
		if trans[i].RepaymentDate.Unix()<nowTime.Unix(){
			//执行转账
			res:=transferAccounts(stub,trans[i].Company,companyArg["buyer"],trans[i].FinancialOrg,companyArg["financial_org"],trans[i].Value)
			if res.Status!=shim.OK{
				return peer.Response{
					Status:               res.Status,
					Message:              res.Message,
					Payload:              nil,
				}
			}
			//修改订单状态
			trans[i].Status=TxStatusRepayed
			//创建组合键
			tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{trans[i].Id})
			if err != nil {
				return shim.Error("create key error ")
			}
			//序列化存入账本
			tranByte,err:=json.Marshal(trans[i])
			if err != nil {
				return shim.Error("marshal error ")
			}
			if err:=stub.PutState(tranKey,tranByte);err!=nil{
				return shim.Error("put state error ")
			}
		}
	}
	return shim.Success(nil)
}

/**
  @Author: dd
  @Date:   2020/5/14 17:40
  @Desc:   验证公司是否存在 *
  @Param:  companyType:string, name:string
  @Return: bool，存在返回true，不存在返回false
**/
func valideCompany(stub shim.ChaincodeStubInterface, companyType, name string) bool {
	// 验证参数
	if companyType==""||name==""{
		return false
	}
	if companyType!=companyArg["financial_org"]||companyType!=companyArg["supplier"]||companyType!=companyArg["buyer"]{
		return false
	}
//	创建组合键
	compKey,err:=stub.CreateCompositeKey(companyType,[]string{name})
	if err != nil {
		return false
	}
//	从账本中获取数据
	compByte,err:=stub.GetState(compKey)
	if err != nil {
		return false
	}
	if len(compByte)==0{
		return false
	}
	return true
}

/**
  @Author: dd
  @Date:   2020/5/14 17:41
  @Desc:   转账 从out转到in  *
  @Param:
  @Return:
**/
func transferAccounts(stub shim.ChaincodeStubInterface, out, outType, in, inType string, number uint64) peer.Response {
	if out==""||outType==""||in==""||inType==""||number<=0{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	if out!=companyArg["financial_org"]||out!=companyArg["supplier"]||out!=companyArg["buyer"]||in!=companyArg["financial_org"]||in!=companyArg["supplier"]||in!=companyArg["buyer"]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "没有此企业类型",
			Payload:              nil,
		}
	}
//  验证企业是否存在
	 if !valideCompany(stub,outType,out){
	 	return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "未找到此企业",
			Payload:              nil,
		}
	 }
	 if !valideCompany(stub,inType,in){
	 	return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "未找到此企业",
			Payload:              nil,
		}
	 }
//	 创建组合键
	outKey,err:=stub.CreateCompositeKey(outType,[]string{out})
	if err != nil {
		return shim.Error("create key error ")
	}
//	从账本中获取数据
	outByte,err:=json.Marshal(outKey)
	if err != nil {
		return shim.Error("marshal error ")
	}
//	反序列化
	var outcomp Company
	if err:=json.Unmarshal(outByte,&outcomp);err!=nil{
		return shim.Error("unmarshal error ")
	}
	//	 创建组合键
	inKey,err:=stub.CreateCompositeKey(inType,[]string{in})
	if err != nil {
		return shim.Error("create key error ")
	}
//	从账本中获取数据
	inByte,err:=json.Marshal(inKey)
	if err != nil {
		return shim.Error("marshal error ")
	}
//	反序列化
	var incomp Company
	if err:=json.Unmarshal(inByte,&incomp);err!=nil{
		return shim.Error("unmarshal error ")
	}
//	判断余额
	if outcomp.Balance<number{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "余额不足",
			Payload:              nil,
		}
	}
	outcomp.Balance-=number
	incomp.Balance+=number
//	序列化存入账本
	outByteNew,err:=json.Marshal(outcomp)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(outKey,outByteNew);err!=nil{
		return shim.Error("put state error ")
	}
	//	序列化存入账本
	inByteNew,err:=json.Marshal(incomp)
	if err != nil {
		return shim.Error("marshal error ")
	}
	if err:=stub.PutState(inKey,inByteNew);err!=nil{
		return shim.Error("put state error ")
	}
	return shim.Success(nil)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:45
  @Desc:   根据企业类型获取企业信息 *
  @Param:  companyType:string 企业类型
  @Return: companys:[]Company
**/
func getCompany(stub shim.ChaincodeStubInterface, args []string) peer.Response {
//	验证参数
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
	if args[0]!=companyArg["financial_org"]||args[0]!=companyArg["supplier"]||args[0]!=companyArg["buyer"]{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "没有此企业类型",
			Payload:              nil,
		}
	}
// 根据前缀从账本中获取数据
	result,err:=stub.GetStateByPartialCompositeKey(args[0],[]string{})
	if err != nil {
		return shim.Error("GetStateByPartialCompositeKey error ")
	}
	var comps []Company
//	最后关闭结果集
	defer result.Close()
// 遍历结果集
	for result.HasNext(){
		val,err:=result.Next()
		if err != nil {
			return shim.Error("next error ")
		}
	//	反序列化
		var comp Company
		if err:=json.Unmarshal(val.GetValue(),&comp);err!=nil{
			return shim.Error("unmarshal error")
		}
	//	追加至数组
		comps= append(comps, comp)
	}
	compsByte,err:=json.Marshal(comps)
	if err != nil {
		return shim.Error("marshal error ")
	}
	return shim.Success(compsByte)
}

/**
  @Author: dd
  @Date:   2020/5/15 17:37
  @Desc:   获取买方的交易信息 *
  @Param:  buyer 买方公司名
  @Return: {transactions:[]Transaction,unfinished:int,total:int,violateTreaty:int}
			分别为此买方的交易信息、未完成交易数、交易总数、违约交易数（实际还款时间RepayDate大于应还款时间RepaymentDate）z
**/
func getTrByBuyer(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	//	验证参数
	if len(args)!=1{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数长度错误",
			Payload:              nil,
		}
	}
	if args[0]==""{
		return peer.Response{
			Status:               shim.ERRORTHRESHOLD,
			Message:              "参数为空",
			Payload:              nil,
		}
	}
//	查询所有订单
	res:=getTransactions(stub,[]string{})
	if res.Status!=shim.OK{
		return peer.Response{
			Status:               res.Status,
			Message:              res.Message,
			Payload:              nil,
		}
	}
// 反序列化
	var trans []Transaction
	if err:=json.Unmarshal(res.Payload,&trans);err!=nil{
		return shim.Error("unmarshal error ")
	}
	var unfinished,total,violateTreaty int
	var transactions []Transaction
	//	遍历数组
	for i:=0;i<len(trans);i++{
		// 寻找买家订单
		if trans[i].Company==args[0]{
			transactions= append(transactions, trans[i])
			total++
			if trans[i].Status!=TxStatusRepayed{
				unfinished++
			}
			if trans[i].RepaymentDate.Unix()<trans[i].RepayDate.Unix(){
				violateTreaty++
			}
		}
	}
	buyertrans:=make(map[string]interface{})
	buyertrans["transactions"]=transactions
	buyertrans["unfinished"]=unfinished
	buyertrans["total"]=total
	buyertrans["violateTreaty"]=violateTreaty
//	序列化
	buyertransByte,err:=json.Marshal(buyertrans)
	if err != nil {
		return shim.Error("marshal error ")
	}
	return shim.Success(buyertransByte)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:04
  @Desc:   获取交易信息  根据Id查询交易，不传数组则查询所有
  @Param:  [id0,id1] []string
  @Return: transactions []Transaction
**/
func getTransactions(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	// 检查参数的个数
	if len(args) > 1 {
		return shim.Error("invalid args.")
	}
	// 所有要查询的key，如果为空则查询所有
	var keys []string

	// 验证参数的正确性
	if len(args) == 1 {
		// 将第一个参数取出来反序列化为[]string
		var argKeys []string
		if err := json.Unmarshal([]byte(args[0]), &argKeys); err != nil {
			return shim.Error(fmt.Sprintf("unmarshal error: %s", err))
		}

		keys = append(keys, argKeys...)
	}

	var transactions []Transaction
	if len(keys) == 0 {
		// 传入的keys长度为0，则查找并返回所有数据
		// 通过主键从区块链查找相关的数据
		resultIterator, err := stub.GetStateByPartialCompositeKey(TransactionKeyPrefix, keys)
		if err != nil {
			return shim.Error(fmt.Sprintf("query transactions error: %s", err))
		}
		defer resultIterator.Close()

		// 检查返回的数据是否为空，不为空则遍历数据，否则返回空数组
		for resultIterator.HasNext() {
			val, err := resultIterator.Next()
			if err != nil {
				return shim.Error(fmt.Sprintf("resultIterator error: %s", err))
			}

			var transaction Transaction
			if err := json.Unmarshal(val.GetValue(), &transaction); err != nil {
				return shim.Error(fmt.Sprintf("unmarshal error: %s", err))
			}

			transactions = append(transactions, transaction)
		}
	} else {
		// 传入的keys长度不为0，查找相应的数据并返回
		for _, v := range keys {
			// 创建组合键
			key, err := stub.CreateCompositeKey(TransactionKeyPrefix, []string{v})
			if err != nil {
				return shim.Error(fmt.Sprintf("CreateCompositeKey error: %s", err))
			}

			// 从账本中获取数据
			partBytes, err := stub.GetState(key)
			if err != nil {
				return shim.Error(fmt.Sprintf("GetState error: %s", err))
			}

			if len(partBytes) != 0 {
				// 反序列化数据
				var transaction Transaction
				err = json.Unmarshal(partBytes, &transaction)
				if err != nil {
					return shim.Error(fmt.Sprintf("Unmarshal error: %s", err))
				}

				// 追加进结果数组
				transactions = append(transactions, transaction)
			}
		}
	}

	//序列化数据
	result, err := json.Marshal(transactions)
	if err != nil {
		return shim.Error(fmt.Sprintf("marshal error: %s", err))
	}

	return shim.Success(result)
}

/**
  @Author: dd
  @Date:   2020/5/15 18:07
  @Desc:   查询此交易的历史信息
  @Param:  id:string
  @Return:
**/
func getTransactionHistory(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	// 检查参数的个数
	if len(args) != 1 {
		return shim.Error("只需要一个参数：订单id")
	}

	// 创建组合键
	compositeKey, err := stub.CreateCompositeKey(TransactionKeyPrefix, args)
	if err != nil {
		return shim.Error(fmt.Sprintf("CreateCompositeKey error: %s", err))
	}

	// 获取该key的历史，返回一个迭代器
	resultIterator, err := stub.GetHistoryForKey(compositeKey)
	if err != nil {
		return shim.Error(fmt.Sprintf("GetHistoryForKey error: %s", err))
	}
	defer resultIterator.Close()

	// buffer是一个包含了订单历史记录的JSON数组
	var buffer bytes.Buffer
	buffer.WriteString("[")

	bArrayMemberAlreadyWritten := false
	// 遍历迭代器，将值取出来
	for resultIterator.HasNext() {
		response, err := resultIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		// 在数组元素前加",",第一个元素前不加
		if bArrayMemberAlreadyWritten == true {
			buffer.WriteString(",")
		}
		buffer.WriteString("{\"TxId\":")
		buffer.WriteString("\"")
		buffer.WriteString(response.TxId)
		buffer.WriteString("\"")

		buffer.WriteString(", \"Value\":")
		// 如果该记录的操作是删除，则返回null，否则返回数据的值
		if response.IsDelete {
			buffer.WriteString("null")
		} else {
			buffer.WriteString(string(response.Value))
		}

		buffer.WriteString(", \"Timestamp\":")
		buffer.WriteString("\"")
		buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String())
		buffer.WriteString("\"")

		buffer.WriteString(", \"IsDelete\":")
		buffer.WriteString("\"")
		buffer.WriteString(strconv.FormatBool(response.IsDelete))
		buffer.WriteString("\"")

		buffer.WriteString("}")
		bArrayMemberAlreadyWritten = true
	}

	buffer.WriteString("]")

	fmt.Printf("getHistoryForPatent returning:\n%s\n", buffer.String())

	// 返回结果
	return shim.Success(buffer.Bytes())
}

func main() {
	err := shim.Start(new(SupplyChainFinance))
	if err != nil {
		fmt.Printf("Error starting chaincode: %s", err)
	}
}
